-
Notifications
You must be signed in to change notification settings - Fork 54
Add the affected program address to each InstructionError
#74
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Add the affected program address to each InstructionError
#74
Conversation
This is a bit of a spitball pr. Things I'm thinking about:
|
fcc12a6
to
270d3c8
Compare
270d3c8
to
d7fbd88
Compare
/// third element indicates the address of the program that raised the error, if applicable; the | ||
/// error could after all have been raised during a cross-program invocation (ie. in an inner | ||
/// instruction). | ||
InstructionError(u8, InstructionError, Option<Pubkey>), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We won't have a program address in cases where the error is InstructionError::UnsupportedProgramId
, so this is made an Option
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you elaborate what cases UnsupportedProgramId
is for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, for sure. It's thrown, for instance, here:
ie. if you tried to issue an instruction without providing the address of a program.
The larger point here is that there exist InstructionErrors
that are more like ‘there was a structural problem with this instruction’ rather than ‘a program died and here's why.’ The latter has a program address associated with it while the former may not.
btw this is a breaking change, but we're already due a bump to 3.0 because of #46 |
/// third element indicates the address of the program that raised the error, if applicable; the | ||
/// error could after all have been raised during a cross-program invocation (ie. in an inner | ||
/// instruction). | ||
InstructionError(u8, InstructionError, Option<Pubkey>), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
adding Option<Pubkey>
here means TransactionError
is now 64 bytes instead of 32 bytes. I'm not sure how often we move/clone these on the agave side, but this could have some small perf implications. I'm aware of at least a few places we clone these values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
^ this is not a comment on why we shouldn't do this - just a note that we should be aware of this size change, and be more aware of where we're cloning these in our processing pipeline so we can avoid performance hits
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feels bad. I should probably endeavour to store just the index of the program account in the accounts array, and then make the downstream thing that really wants to know what the program was look it up.
I'll rifle through the Agave code and see if that's tractable (ie. the instruction will need to be available wherever something needs know what program address was involved).
So, here's what I'm thinking. There are three ways to approach this. Option 1 – Add program address to
|
So good news, I went through all of the To go with that, the I'm down to go with the option 1, but using a It'll be a bit of a slog to get through all the changes, but it should be mostly straightforward. Happy to hear other ideas though! [1] if I'm incorrect, then we should fix the usage of that particular error variant rather than torpedo the design |
I started then scrapped a PR that did option 1 and I seem to remember it being really hard to obtain the program address in places. Here's I can try again, but a few on spec:
The big problem is here, because it takes in a dynamic error after long having forgotten what program is responsible for the error: (link) So basically you have to follow |
That one looks at the owner of the first program account in the transaction context, so we could probably use that, right? https://github.com/anza-xyz/agave/blob/ccbf3f25f332cf4bfa4f1a9bf27db8d3333b3064/program-runtime/src/invoke_context.rs#L523
If they do, then that's an issue with their usage, which should be fixable.
That plumbing does look a bit involved, but should end up similar to any big refactor. |
@joncinque @steveluscher Hey guys, sorry to come in here late! Another major issue I see with obtaining the program ID for an inner instruction from the transaction accounts is that CPI callees will eventually no longer be in that list at all. If a program decides to hard-code Rather than plumbing callee IDs all the way from SVM, what about just enabling inner instructions recording on Bank all of the time, and walking that payload to grab the program ID? The array of inner instructions comes back empty when there's an error, but we can just change that behavior. |
Problem
Consider a transaction error that originates from a cross-program invocation (ie. an inner instruction). Currently TransactionError returns you the index of the outer instruction, which in no way helps you to correlate the content of the error message with the actual program from whence it came.
Summary of changes
Added
program_address
to theInstructionError
type, which will help consumers correlate instruction errors with their actual source.Addresses anza-xyz/agave#5152.